Introduction to Machine Learning

Chapter 03: K-Nearest Neighbors

1. Introduction

The KNN algorithm is the first supervised classification model we will study in depth. Its usefulness comes from its simplicity: to classify a new point, look at the k closest labeled training points and take a majority vote. This unit covers the algorithm's place in the taxonomy of ML methods, distance metrics, the critical choice of k, the equal-vote problem, and how weighted KNN fixes it.

Learning Objectives

2. Theory

2.1 ML Algorithm Taxonomy

Before looking at KNN itself, it helps to place it in the usual algorithm taxonomy. Two distinctions are relevant here: whether an algorithm is parametric or non-parametric, and whether it is a lazy or an eager learner. The two tables below compare them.

Parametric vs. Non-Parametric
Lazy vs. Eager
DimensionParametricNon-Parametric
Parameter countFixed, independent of data sizeGrows with data size
AssumptionsStrong (linearity, normality, …)Few / none
ExamplesLinear Regression, Logistic Regression, Naïve BayesKNN, Decision Trees, Ensembles
ProsFast, require less dataFlexible, capture complex patterns
ConsToo restrictive if assumptions failNeed more data, computationally costly
DimensionLazy LearningEager Learning
Training phaseStores the data only (zero compute)Builds explicit model immediately
Work happens when?Prediction timeTraining time
Speed: trainFastSlow
Speed: predictSlow (O(n) per prediction)Fast
ExampleKNN, case-based reasoningNeural Networks, Linear Regression, Decsion Trees
KNN is both Non-Parametric and Lazy. That combination makes it simple, flexible, and interpretable — but slow at prediction and hungry for clean, scaled features.

2.2 The Standard (Uniform) KNN Algorithm

In the standard version of the algorithm, all selected neighbors have an equal say in the prediction. For a query instance whose class we want to predict, the procedure is:

  1. Choose an integer \(K\) representing the number of nearest neighbors.
  2. Compute the distance between the query instance \(x_0\) and every training example.
  3. Sort distances in ascending order and retain the \(K\) closest points (defining the neighborhood \(\mathcal{N}_0\)).
  4. Gather the class labels of those \(K\) neighbors.
  5. Return the simple majority class among the \(K\) neighbors as the prediction.

Formally, KNN computes the estimated conditional probability that a query observation \(x_0\) belongs to class \(j\) as the fraction of points in its \(K\)-nearest neighborhood \(\mathcal{N}_0\) whose response equals \(j\):

\[ P(Y = j \mid X = x_0) = \frac{1}{K} \sum_{i \in \mathcal{N}_0} I(y_i = j) \]

where \(I(y_i = j)\) is an indicator function that equals \(1\) if the \(i\)-th neighbor belongs to class \(j\), and \(0\) otherwise. The observation \(x_0\) is then assigned to the class \(j\) with the largest estimated conditional probability.

Classic k = 3 vs. k = 5 diagram

K-nearest neighbors classification diagram A green query point is classified using two neighborhood rings. The k equals 3 ring contains two red triangles and one blue square, producing Class B. The k equals 5 ring contains two red triangles and three blue squares, producing Class A. K-nearest neighbors classification The class is determined by the majority of neighboring points. Feature space Query-based neighborhood comparison k = 5 ring · larger k = 3 ring New query unknown class Legend Class A Blue square Class B Red triangle New test point Neighborhood results k = 3 2 B · 1 A k = 5 2 B · 3 A Predicted class Using k = 3 Class B majority: 2 / 3 Neighbor vote: the most common class among the selected points determines the prediction. s*

2.3 Distance Metrics

A valid metric d must satisfy four axioms: non-negativity d(x1,x2) ≥ 0; self-proximity d(x,x) = 0; symmetry d(x1,x2) = d(x2,x1); and triangle inequality d(x1,x2) ≤ d(x1,x3) + d(x3,x2).

Euclidean
Manhattan
Minkowski

The Euclidean distance is the L2 norm, that is, the ordinary straight-line distance between two points in ℝⁿ.

\( d_E(\mathbf{x}^{(i)}, \mathbf{x}^{(j)}) = \sqrt{\sum_{k=1}^{n} \left( x_k^{(i)} - x_k^{(j)} \right)^2} \)

It is the default metric for KNN in scikit-learn and matches the everyday notion of distance. It is also sensitive to feature scale, which is why the features must be standardized before it is used.

The Manhattan distance is the L1 norm, also called the city-block or taxicab distance. Instead of measuring a straight line, it adds the displacements along each axis.

\( d_M(\mathbf{x}^{(i)}, \mathbf{x}^{(j)}) = \sum_{k=1}^{n} \left| x_k^{(i)} - x_k^{(j)} \right| \)

It is more robust to outliers than the Euclidean distance, and it is often a better choice when the features have mixed types after encoding.

The Minkowski distance generalizes both of the previous metrics. The order p is an additional hyperparameter:

\( d_{\text{Mink}}(\mathbf{x}^{(i)}, \mathbf{x}^{(j)}) = \left( \sum_{k=1}^{n} \left| x_k^{(i)} - x_k^{(j)} \right|^p \right)^{\frac{1}{p}} \)
  • p = 1 → Manhattan
  • p = 2 → Euclidean
  • p → ∞ → Chebyshev (max-coordinate difference)

2.4 Choosing the Right k

The value of k controls the complexity of the model. A small k lets the prediction follow every local detail of the training data, while a large k produces a smoother decision boundary. The table below shows how this trade-off behaves across the range of k.

kModel ComplexityBehaviorRisk
1 (very small)HighestMemorizes every training point; jagged decision boundaryOverfit — sensitive to noise and outliers
3, 5, 7 (odd)High / MediumFlexible, locally adaptive boundariesBalanced (good default starting point)
≈ √n or 10–20% of nModerateSmoother boundariesUnderfit risk starts growing
n (all points)LowestAlways predicts the majority class — a trivial baselineUnderfit — ignores all local structure

Practical rules of thumb

2.5 Why Scaling Is Mandatory for KNN

KNN decides everything on the basis of distance, so a feature measured on a large numerical scale will dominate the distance calculation even when it is not the more informative feature. The following example shows how large this effect can be.

The Scaling Catastrophe

Consider two points: Age=28 vs. 38, Salary=$100,000 vs. $150,000. Euclidean distance without scaling:

\( \sqrt{(38-28)^2 + (150{,}000-100{,}000)^2} \approx \sqrt{100 + 2{,}500{,}000{,}000} \approx 50{,}000 \)

The salary difference of $50K completely dominates the 10-year age difference. After standardization, each feature is measured in SD units and both contribute fairly to the distance.

2.6 KNN Decision Boundaries

The figure below illustrates KNN in action on a simple dataset with six blue and six orange observations.

K-Nearest Neighbors (KNN) Classification (K = 3) A side-by-side diagram illustrating the KNN classifier. The left panel shows a green circular neighborhood identifying the 3 nearest neighbors to a test point X. The right panel displays the full decision boundary dividing the feature space into blue and orange prediction regions.

Left: A test observation (black cross) is shown. With K = 3, the three closest points (inside the circle) are identified. Two are blue and one is orange → the query is predicted as blue.

Right: The KNN decision boundary for K = 3 is shown in black. The blue grid indicates the region where a test point would be classified as blue; the orange grid indicates the region where it would be classified as orange.

The choice of K has a drastic effect on the decision boundary as shown in the following diagrma:

Key Insight: K Controls Boundary Flexibility

Small K → flexible, jagged boundaries, sensitive to noise (overfitting risk).
Large K → smooth, simple boundaries, ignores local patterns (underfitting risk).
The optimal K balances these two extremes, giving a boundary that captures true structure without memorizing noise.

2.6 The Equal-Vote Problem and Weighted KNN

In standard KNN each of the k neighbours gets exactly one vote, regardless of how far it is from the query point. This can produce counter-intuitive predictions, as shown below.

When “one neighbour, one vote” fails

Suppose k = 5 for a new query point. The neighbours of Class A are at distances {0.1, 5.0}; the neighbours of Class B are at {4.8, 4.9, 5.1}. Standard KNN counts 3 B vs 2 A and predicts B. Yet the closest neighbour (distance 0.1) clearly belongs to A, and that strong evidence is completely ignored.

The natural solution is distance-weighted voting: assign a weight to each neighbour that decreases with distance, then sum weights per class and predict the class with the largest total.

2.7 Formal Weighted KNN – The (K+1) Normalisation Approach

A well-known formulation from the literature (Weighted k-Nearest-Neighbor Techniques and Ordinal Classification, 2004) defines a weighted scheme in which the distances of the nearest neighbours are first scaled relative to the local neighbourhood. The algorithm is:

Weighted KNN using (K+1)-th neighbour for normalisation

  1. Find K+1 nearest neighbours of the query point \(x\).
  2. Let \(d(x, x_{(K+1)})\) be the distance to the \((K+1)\)-th neighbour. This distance provides a reference scale for the local neighbourhood.
  3. For each of the first \(K\) neighbours, compute the normalised distance: \[ D(i) = \frac{d(x, x_{(i)})}{d(x, x_{(K+1)})}. \] Because the first \(K\) neighbours are no farther away than the \((K+1)\)-th neighbour, these normalised distances satisfy \(0 \leq D(i) \leq 1\).
  4. Apply a transformation function \(f(D)\) to obtain the weight: \[ w_i = f\bigl(D(i)\bigr). \] The function is chosen so that closer neighbours receive greater weight. For example:
    • \(f(D) = 1/D\)   (inverse distance – strongly emphasises close neighbours)
    • \(f(D) = 1-D\)   (linear decay)
    • \(f(D) = \exp(-D^2)\)   (Gaussian-like smooth decay)
  5. Predict using the weighted sum per class: \[ \operatorname{argmax}_c \sum_{i \in \text{class } c} w_i. \]

Important distinction: \(D(i)\) is a normalised distance, not the final weight. A smaller \(D(i)\) means that the neighbour is closer. The weighting function \(f\) then converts that distance into a weight, typically giving a larger weight to a smaller distance.

Key advantage: Normalising by the \((K+1)\)-th distance expresses each neighbour's distance relative to the local neighbourhood scale.

2.8 Practical Simplification – Inverse-Distance Weighting

One particularly simple choice is inverse-distance weighting, where the weight is inversely proportional to the neighbour's distance:

$$ w_i = \frac{1}{d_i}. $$

This is the weighting used by sklearn.neighbors.KNeighborsClassifier when weights='distance'.

At first glance, this may look different from the normalised formulation above. However, when the weighting function is \(f(D)=1/D\), the two forms are equivalent for classification. Since

$$ D(i)=\frac{d_i}{d_{K+1}}, $$

the inverse weight used in the 2004 formulation becomes

$$ w_i=\frac{1}{D(i)} =\frac{1}{d_i/d_{K+1}} =\frac{d_{K+1}}{d_i}. $$

The factor \(d_{K+1}\) is the same for every one of the \(K\) neighbours. It therefore multiplies every weight by the same constant and does not change which class has the largest total weight. Thus, for inverse-distance weighting, we can equivalently use the much simpler formula

$$ \boxed{w_i=\frac{1}{d_i}}. $$

Seeing the Equivalence with a Simple Example

Suppose K = 3, and the four nearest neighbours are at distances \(1, 2, 3,\) and \(4\). The fourth neighbour provides the \((K+1)\)-th distance used for normalisation.

Neighbour Distance \(d_i\) Normalised Distance \(D(i)=d_i/4\) Inverse Weight \(1/D(i)\) Simple Weight \(1/d_i\)
1st10.254.0001.000
2nd20.502.0000.500
3rd30.751.3330.333

Notice that the normalised distance is smallest for the closest neighbour. This is exactly what we expect: the closest neighbour has the smallest distance.

We then apply the inverse function \(1/D\). This reverses the ordering, so the smallest distance produces the largest weight:

$$ 1/0.25=4,\qquad 1/0.50=2,\qquad 1/0.75\approx1.333. $$

These are simply the ordinary inverse-distance weights multiplied by the same constant, \(4\):

$$ 4 = 4\times1,\qquad 2 = 4\times0.5,\qquad 1.333\approx4\times0.333. $$

Therefore, the two sets of weights have exactly the same relative ordering and produce the same class prediction. The normalisation changes the numerical values of the weights, but not the outcome of the weighted vote.

This equivalence is specific to inverse-distance weighting. With other functions, such as a triangular or Gaussian function, applying the function to the normalised distance \(d_i/d_{K+1}\) is generally not the same as applying it directly to the raw distance \(d_i\).

The customer example below uses the simple inverse-distance formulation because it is straightforward to compute and is the form used by scikit-learn for weights='distance'.

2.9 Worked Example – Weighted KNN in Action

Using the scaled customer dataset and query point David, with K = 3. As in the equivalence example above, we look one neighbour beyond K — the 4th nearest neighbour — purely to provide the standardising distance, not to vote.

Neighbour Distance \(d_i\) Standardised Distance \(D(i) = d_i / d_{(K+1)}\) Similarity Weight \(1/D(i)\) Class
John0.3490.3622.759Yes
Rachael0.3660.3802.631No
Norah0.7310.7591.317Yes
Jefferson0.963NA — used only to standardiseNANo
Ruth1.157NA — outside K+1NANo

3. Interactive Examples

Example 1: Classify a Point with k = 3 and k = 5

Given a tiny 2-D training set. Compute for yourself, then reveal.

PointXYClass
P10.30.7A
P20.20.9B
P30.60.6A
P40.50.1A
P50.70.7B
P60.40.9B
Query Q0.20.6?
Step 1: Compute Euclidean distances from Q to all 6 points (click)

d(Q, P₁) = √[(0.3−0.2)² + (0.7−0.6)²] = √(0.02) ≈ 0.141 (A)

d(Q, P₂) = √[(0.0)² + (0.3)²] = 0.300 (B)

d(Q, P₃) = √[(0.4)² + (0.0)²] = 0.400 (A)

d(Q, P₄) = √[(0.3)² + (0.5)²] = √(0.34) ≈ 0.583 (A)

d(Q, P₅) = √[(0.5)² + (0.1)²] = √(0.26) ≈ 0.510 (B)

d(Q, P₆) = √[(0.2)² + (0.3)²] = √(0.13) ≈ 0.361 (B)

Predictions: (a) k = 3 standard KNN   (b) k = 5 standard KNN.

Sorted distances: {0.141 (A), 0.300 (B), 0.361 (B), 0.400 (A), 0.510 (B), 0.583 (A)}

(a) k = 3 neighbors: {A, B, B} → majority B → Predict Class B.

(b) k = 5 neighbors: {A, B, B, A, B} → 3 B, 2 A → Predict Class B.

Example 2: When Scaling Destroys the Distance

Scale-or-Not Scenario

Two features: house_sqft (range 800–4,000) and num_bedrooms (range 1–6).

House X: 1,200 sqft, 2 beds.   House Y: 1,800 sqft, 3 beds.

Without any scaling, d(X,Y) ≈ √(600² + 1²) ≈ 600 — the bedroom difference is invisible.

  1. What is the qualitative effect of applying Z-score standardization before distance?
  2. If we used Manhattan distance instead of Euclidean on the raw values, would that help?

(a) Standardization rescales each feature to SD units. Typical SDs: sqft ≈ 700, bedrooms ≈ 1.2. SD units difference: sqft 600/700 ≈ 0.86 SD, bedrooms 1/1.2 ≈ 0.83 SD. After standardization, both features contribute approximately equally to the distance — exactly what we want.

(b) No. Manhattan on raw data still sums: 600 + 1 = 601. The bedroom difference still vanishes. All distance metrics need scale alignment when feature scales differ.

Example 3: Weighted KNN vs. Standard KNN

Query point Q. K = 5. Distances and classes of nearest 5: { d=0.05 A, d=0.98 B, d=0.99 B, d=1.00 B, d=1.01 A }.

  1. Prediction of standard KNN?
  2. Prediction of weighted KNN using w = 1 / d?
  3. Why is there a difference? Which is more sensible?

(a) Standard KNN counts: 3 B vs. 2 A → Predict B.

(b) Weights: A gets 1/0.05 + 1/1.01 ≈ 20 + 0.99 = 20.99. B gets 1/0.98 + 1/0.99 + 1/1.00 ≈ 1.02 + 1.01 + 1.00 = 3.03. Weighted sum A > B → Predict A.

(c) Difference arises because that one extremely close neighbor at d = 0.05 is a very strong signal for A. Weighted KNN is more sensible here because it respects proximity. Always compare weights='uniform' vs. weights='distance' in cross-validation.

Note: we skip the K+1 normalization step here since w = 1/d is the special case where it's mathematically redundant — normalizing by the 6th neighbor would only rescale every weight by the same constant, leaving the ranking and prediction unchanged (see Section 2.8). For any other kernel, always normalize first.

4. Numerical Solutions

Problem 1: Manhattan, Euclidean, and Minkowski

Two 4-dimensional standardized points: p = [0.1, −0.3, 0.5, 0.0] and q = [0.3, 0.1, −0.2, 0.7]. Compute (a) Manhattan distance, (b) Euclidean distance, and (c) Minkowski distance with p = 3.

📘 Step-by-step solution

First, coordinate-wise differences: p − q = [−0.2, −0.4, 0.7, −0.7]. Absolute values: |p − q| = [0.2, 0.4, 0.7, 0.7].

(a) Manhattan (L1): sum of absolute values.

\( d_M = 0.2 + 0.4 + 0.7 + 0.7 = \mathbf{2.0} \)

(b) Euclidean (L2): root of sum of squares.

\( d_E = \sqrt{0.04 + 0.16 + 0.49 + 0.49} = \sqrt{1.18} \approx \mathbf{1.086} \)

(c) Minkowski with p = 3: (sum of absolute differences cubed)^(1/3).

\( d_{M3} = \sqrt[3]{0.2^3 + 0.4^3 + 0.7^3 + 0.7^3} = \sqrt[3]{0.008 + 0.064 + 0.343 + 0.343} = \sqrt[3]{0.758} \approx \mathbf{0.912} \)

Problem 2: KNN with a Tie and Weighted KNN

K = 4 (deliberately even, so ties can happen). Four nearest neighbors of a query: {d=0.2 → class 0, d=0.3 → class 1, d=0.5 → class 0, d=0.6 → class 1}.

  1. Show that standard KNN gives a perfect 2/2 tie and describe two sensible tiebreakers.
  2. Apply weighted KNN with w = 1 / d. Does this break the tie?
📘 Step-by-step solution

(a) Standard KNN counts: 2 votes for class 0, 2 votes for class 1 → tie 50/50. Common tiebreakers: (i) pick the class of the single nearest neighbor (class 0 wins); (ii) use weighted KNN; (iii) prefer the class with higher overall prior in the whole training set; (iv) randomly sample (weak!).

(b) Weights per neighbor: w(0@0.2) = 5; w(1@0.3) ≈ 3.333; w(0@0.5) = 2; w(1@0.6) ≈ 1.667. Sums: Class 0 total = 5 + 2 = 7; Class 1 total ≈ 3.333 + 1.667 = 5.00.

\( \text{Weighted class 0} = 7 > \text{Weighted class 1} = 5 \implies \text{Predict }\mathbf{0} \)

Yes — weighting cleanly resolves the tie in favor of the closer class-0 neighbors.

Note: we skip the K+1 normalization step here since w = 1/d is the special case where it's mathematically redundant — normalizing by the 5th neighbor would only rescale every weight by the same constant, leaving the ranking and prediction unchanged (see Section 2.8). For any other kernel, always normalize first.

Problem 3: Sensitivity of k – Overfitting vs. Underfitting by Hand

You have 8 training points, 2-D. Two are mislabeled noise: one red in a blue cluster, one blue in a red cluster. Answer qualitatively with justifications:

  1. At k = 1, how do the two noisy points affect predictions in their immediate neighborhoods?
  2. At k = 7, how do they affect predictions?
  3. Which k value is more likely to overfit (memorize the noise)? Which is more likely to underfit (oversmooth and ignore local structure)?
📘 Step-by-step solution

(a) k = 1: The two mislabeled points each "own" a little Voronoi cell around themselves. Any query that lands nearer to them than to any correctly-labeled neighbor will be predicted wrong. The decision boundary becomes highly flexible and follows the training data very closely, making it extremely sensitive to local noise – this is the overfitting regime.

(b) k = 7 (out of 8): Every prediction is a near-majority vote over almost the whole dataset. The two noisy points contribute 2/7 of a vote to queries everywhere, shifting every prediction slightly but smoothly toward the wrong class. The decision boundary is very smooth but too simple – it fails to capture the true local cluster structure. This is the underfitting regime.

(c) k = 1 overfits – it memorizes the noise and produces erratic local predictions that are highly sensitive to individual points. k = 7 underfits – it oversmooths and ignores the meaningful local patterns in the data. The optimal k (e.g., 3 or 5) balances flexibility with smoothness, capturing the true structure without being overly sensitive to noise.

5. Try It Yourself

Problem 1 — Minkowski Distance Practice

Two points on a 2-D standardized plane: a = (1.0, −0.5), b = (2.0, 1.5).

  1. Compute Minkowski distance at order p = 1, p = 2, and p = 3.
  2. Verify numerically that d₁ ≥ d₂ ≥ d∞ on this example. Which metric most penalizes large individual coordinate errors?

|Δx| = 1, |Δy| = 2.

(a)

\( d_1 = 1 + 2 = \mathbf{3} \) \( d_2 = \sqrt{1^2 + 2^2} = \sqrt{5} \approx \mathbf{2.236} \) \( d_3 = \sqrt[3]{1^3 + 2^3} = \sqrt[3]{1 + 8} = \sqrt[3]{9} \approx \mathbf{2.080} \)

(b) 3 ≥ 2.236 ≥ 2.080 ✓ holds. As p increases, the distance approaches the larger coordinate (2.0). Higher p values increasingly penalize the largest coordinate difference while reducing the influence of smaller differences. L2 (p=2) provides a balanced middle ground.

Problem 2 — Preprocessing Checklist for KNN

You are given an adult-income dataset with these features. For each column, say YES / NO / MAYBE for whether the described transformation should happen before KNN, with a one-sentence justification.

  1. age (years, 17–90) → StandardScaler Z-score?
  2. workclass (Private / Self-emp-not-inc / … / Never-worked) → LabelEncoder to integers 0..7?
  3. education_num (1 = Preschool through 16 = Doctorate) → Leave as is because it's already numeric?
  4. native_country (42 countries) → One-hot encoding to 41 dummy columns?
  5. Rows with missing occupation = ? → Drop rows?
  1. YES. Continuous numeric feature; distance-based algorithm needs all features on SD scale.
  2. NO. Never use LabelEncoder on nominal X features — it creates a fake ordering ("Private" < "Self-emp"?). One-hot encode instead.
  3. MAYBE but still scale it. It is ordinal with known equal-ish steps, so leaving 1..16 is acceptable, but it should still be standardized along with the other numeric columns to avoid 16–1 range dominating SD-unit distances from age/income.
  4. YES. Correct nominal encoding. (Bonus: 41 columns is high-dimensional for KNN, so consider pairing with chi-square feature selection later.)
  5. MAYBE. If "?" is rare and not MCAR, impute or assign a dedicated Missing category + indicator rather than dropping the whole row.
Problem 3 — Weighted KNN with 1−D

We have K = 4 neighbors with distances to query: {1.0, 2.0, 3.0, 4.0}. The (K+1) = 5th neighbor's distance is 5.0 (used for normalization).

  1. Compute normalized distances Dᵢ = dᵢ / dK+1 for i = 1..4.
  2. Compute weights wᵢ = 1 − Dᵢ for each neighbor.
  3. If neighbor classes are {C1, C2, C1, C2} respectively, which class wins the weighted vote?

(a) D = [1/5, 2/5, 3/5, 4/5] = [0.2, 0.4, 0.6, 0.8].

(b) w = 1 − D = [0.8, 0.6, 0.4, 0.2]. (Check: closer points have bigger weights ✓.)

(c) Weighted sums: Class 1 = 0.8 (neighbor 1) + 0.4 (neighbor 3) = 1.2. Class 2 = 0.6 (neighbor 2) + 0.2 (neighbor 4) = 0.8.

\( \text{Winner} = \arg\max(1.2, 0.8) = \mathbf{C1} \)

6. Interactive Quiz

Answer all 5 questions. Click an option for instant feedback.

Your score: 0 / 5

7. Key Takeaways

  1. KNN is lazy + non-parametric. No training computation, no distributional assumptions, works on any shape of decision boundary — at the cost of slow O(n) predictions.
  2. 5-step algorithm: Choose K, compute all distances, sort, keep K nearest, return their majority class. That's the whole algorithm.
  3. Distance metrics. Euclidean (L2) is the intuitive default; Manhattan (L1) is more outlier-robust; Minkowski generalizes both via order p.
  4. K controls the flexibility-smoothness tradeoff. Small k → very flexible, follows training data closely, sensitive to noise, overfit risk. Large k → smoother decision boundaries, less sensitive to noise, underfit risk. Tune via cross-validation; use odd k to avoid 2-class ties.
  5. Scale before KNN, always. Standardization (Z-score) usually beats Min-Max here. Skip scaling → the highest-range feature essentially becomes the only feature.
  6. Weighted KNN fixes the equal-vote problem. Use w = 1/d, or w = 1−D normalized, or Gaussian kernels. sklearn parameter: weights='distance'.
  7. Weighting is a safety net. It reduces the sensitivity to the exact value of k because distant neighbors' contributions naturally fade. Always compare weighted vs. uniform during model selection.

8. Common Pitfalls

  1. Ignoring feature scaling. KNN is entirely distance-based. If you don't standardize, features with large ranges (e.g., salary in dollars) dominate the distance. Weighted KNN (`1/d`) makes this even worse, as an unscaled dominant feature completely distorts inverse-distance weights. Always scale before running KNN.
  2. Choosing k using test-set performance. The test set should be used once, at the very end. If you use it to pick the best k, your reported accuracy will be overly optimistic. Pick k via cross-validation on the training set, then evaluate the final model once on the held-out test set.
  3. Forgetting that prediction is O(n) per query. KNN stores all training data and computes distances to every point at prediction time. For large datasets, this becomes computationally expensive — a key limitation to consider when choosing KNN for a project.
  4. Ignoring feature relevance and the curse of dimensionality. Every feature contributes equally to the distance calculation. Irrelevant features add noise and make neighbors less meaningful. In high dimensions, the curse of dimensionality makes distances converge, causing KNN to degenerate into a coin flip. Always perform feature selection or dimensionality reduction before applying KNN to high-dimensional data.
  5. Setting k too large (e.g., k = n). This predicts the majority class for every query — useful only as a baseline. Any real dataset with local structure will be completely ignored, leading to severe underfitting.